﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.WebPartPages;

namespace SP2010
{
    public static class SiteInfrastructureHelper
    {
        private static PublishingPage CreateCustomPublishingPageImpl(PublishingWeb web, PublishingPageInfo pageInfo)
        {
            PublishingPage newPage = null;
            try
            {
                SPContentTypeId customPageContentTypeID = new SPContentTypeId(pageInfo.ContentTypeId);
                if (customPageContentTypeID == null || customPageContentTypeID == SPContentTypeId.Empty)
                    throw new ArgumentException("Invalid content type specified: " + pageInfo.ContentTypeId);

                // get the Custom Page Layout 
                PageLayout[] layouts = web.GetAvailablePageLayouts(customPageContentTypeID);
                if (layouts.Length < 1)
                    throw new ArgumentOutOfRangeException("Unable to find the specified page layout based on content type id: " + pageInfo.ContentTypeId);

                PageLayout customPageLayout = null;
                int layoutType = (int)pageInfo.LayoutType;
                if (0 <= layoutType && layoutType < layouts.Length)
                {
                    customPageLayout = layouts[layoutType];
                }
                else
                {
                    throw new ArgumentOutOfRangeException("Unable to find the specified page layout based on content type id: " + pageInfo.ContentTypeId + " and layout type: " + pageInfo.LayoutType.ToString());
                }

                // Get / Create the new page's SPFolder 
                SPList pagesList = web.PagesList;
                SPFolder pageFolder = pagesList.RootFolder;

                if (!string.IsNullOrEmpty(pageInfo.FolderName))
                {
                    bool found = false;
                    SPFolderCollection folders = web.PagesList.RootFolder.SubFolders;
                    foreach (SPFolder f in folders)
                    {
                        if (0 == string.Compare(f.Name, pageInfo.FolderName, true))
                        {
                            pageFolder = f;
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        pageFolder.SubFolders.Add(pageInfo.FolderName);
                        pageFolder.Update();
                        pageFolder = pageFolder.SubFolders[pageInfo.FolderName];
                    }
                }


                // If the file exists already, just check it out; otherwise created it.
                // TODO:  Consider deleting and recreating it or reconciling the web part changes to may page creation idempotent.
                try
                {
                    PublishingPage page = web.GetPublishingPage(pageFolder.Url + "/" + pageInfo.Name);
                    if (page != null)
                    {
                        newPage = page;
                        newPage.CheckOut();
                    }
                    else
                    {
                        newPage = web.AddPublishingPage(pageInfo.Name, customPageLayout, pageFolder);
                        newPage.Title = pageInfo.Title;
                        newPage.Update();
                    }
                }
                catch (KeyNotFoundException)
                {
                    newPage = web.AddPublishingPage(pageInfo.Name, customPageLayout, pageFolder);
                    newPage.Title = pageInfo.Title;
                    newPage.Update();

                }

            }
            catch (Exception e)
            {
                string message = string.Format("Unable to create publishing page named '{0}' in web '{1}'", pageInfo.Name, web.Url);
                Exception wex = new Exception(message, e);
                throw wex;
            }

            return newPage;
        }

        /// <summary>
        /// Adds the set of web parts to the SPFile passed in.  Will not add duplicately titled web parts.
        /// </summary>
        /// <param name="pageFile"></param>
        /// <param name="pageInfo"></param>
        private static void AddWebPartsToPage(SPFile pageFile, PublishingPageInfo pageInfo)
        {
            SPLimitedWebPartManager partManager = pageFile.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
            var webParts = from w in pageInfo.WebParts
                           orderby w.Order ascending
                           select w;

            var existingWebParts = partManager.WebParts;

            foreach (var webPart in webParts)
            {

                bool alreadyExists = false;
                foreach (System.Web.UI.WebControls.WebParts.WebPart ew in existingWebParts)
                {
                    if (string.Compare(ew.Title, webPart.WebPart.Title, true) == 0)
                    {
                        alreadyExists = true;
                        break;
                    }
                }

                if (!alreadyExists)
                {
                    partManager.AddWebPart(webPart.WebPart, webPart.Zone, webPart.Order);
                }
            }



        }
        
        private static void EnsureFileIsCheckedOut(SPFile pageFile)
        {
            if (pageFile.CheckOutType == SPFile.SPCheckOutType.None)
            {
                pageFile.CheckOut();
            }
        }
        
        private static void CheckInAndApprovePage(PublishingWeb web, SPFile pageFile, bool isDefaultPage)
        {
            pageFile.CheckIn("Initial page creation.");
            pageFile.Publish("Initial page publish.");
            pageFile.Approve("Initial page approval.");
            pageFile.Update();

            if (isDefaultPage)
            {
                web.DefaultPage = pageFile;
            }

            // Apply all changes done at the web level.
            web.Update();
        }

        public static PublishingPage CreateCustomPublishingPage(PublishingWeb web, PublishingPageInfo pageInfo)
        {

            // Create the basic page
            PublishingPage newPage = CreateCustomPublishingPageImpl(web, pageInfo);
            try
            {
                SPFile pageFile = newPage.ListItem.File;
                EnsureFileIsCheckedOut(pageFile);
                AddWebPartsToPage(pageFile, pageInfo);
                CheckInAndApprovePage(web, pageFile, pageInfo.IsDefaultPage);
            }
            catch (Exception e)
            {
                string message = string.Format("Unable to create publishing page named '{0}' in web '{1}'", pageInfo.Name, web.Url);
                Exception wex = new Exception(message, e);
                throw wex;
            }

            return newPage;
        }

       

        public static void DeleteCustomPublishingPage(PublishingWeb web, string name)
        {
            SPQuery query = new SPQuery();
            query.RowLimit = 10;
            query.Query = "<Where><Eq><FieldRef Name='Name'/><Value Type='Text'>{0}</Value></Eq></Where>";
            PublishingPageCollection pages = web.GetPublishingPages(query);
            if (pages.Count > 0)
            {
                PublishingPage firstPage = pages[0];
                SPListItem item = firstPage.ListItem;
                item.Delete();
            }
        }
    }
}
